package com.xiaokong.changerecord.enums;


import cn.hutool.core.annotation.AnnotationUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.text.StrPool;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.ObjUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.spring.SpringUtil;
import com.xiaokong.changerecord.annotation.ChangeTag;
import com.xiaokong.changerecord.strategy.DictStrategy;
import lombok.AllArgsConstructor;
import lombok.Getter;

import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.function.BiFunction;
import java.util.stream.Collectors;

/**
 * @author Hu_bx
 * @date 10:15 2022/11/14
 **/
@AllArgsConstructor
@Getter
public enum ChangeFormatEnum {


    /**
     *
     */
    AUTO(null),
    CUSTOM(null),
    /**
     * 枚举策略,,根据类型自动处理 格式化策略
     */
    LOCAL_DATE_TIME(new Class[]{LocalDateTime.class}, true, (o, field) -> LocalDateTimeUtil.formatNormal((LocalDateTime) o)),
    LOCAL_DATE(new Class[]{LocalDate.class}, true, (o, field) -> LocalDateTimeUtil.formatNormal((LocalDate) o)),
    DATE_TIME(new Class[]{Date.class}, true, (o, field) -> DateUtil.formatDateTime((Date) o)),
    STRING(new Class[]{String.class, StringBuffer.class, StringBuffer.class}, true, (o, field) -> StrUtil.toString(o)),
    BIG_DECIMAL(new Class[]{BigDecimal.class, Long.class, Float.class, Integer.class, Short.class}, true, (o, field) -> NumberUtil.decimalFormat(",###.##", o)),
    /**
     * 自己实现策略
     */
    DATE((o, field) -> DateUtil.formatDate((Date) o)),
    Y_OR_N((o, field) -> YesOrNoEnum.getDes(o.toString())),
    RATE((o, field) -> NumberUtil.decimalFormat(",###.######", o)),
    /**
     * 字典集合
     */
    DICT_LIST((o, field) -> {
        ChangeTag changeTag = AnnotationUtil.getAnnotation(field, ChangeTag.class);
        List<String> stringList = StrUtil.split(o.toString(), StrPool.COMMA).stream()
                .map(s -> SpringUtil.getBean(DictStrategy.class).getDictByCode(changeTag.dict(), StrUtil.toString(s)))
                .collect(Collectors.toList());
        return CollUtil.join(stringList, StrUtil.COMMA);
    }),

    ;

    public final static String NULL = "空";
    /**
     * 类型
     */
    private Class<?>[] types;
    /**
     * 是否默认
     */
    private final Boolean isDefault;
    /**
     * conversion
     */
    private final BiFunction<Object, Field, String> format;


    ChangeFormatEnum(BiFunction<Object, Field, String> format) {
        this.format = format;
        this.isDefault = false;
    }


    /**
     * 类型格式化
     *
     * @param o 传入类型
     * @return 格式化后字符串
     */
    public static String formatDefault(Object o, Field field) {
        if (ObjUtil.isEmpty(o) || StrUtil.isBlankOrUndefined(StrUtil.toString(o))) {
            return NULL;
        }
        for (ChangeFormatEnum value : Arrays.stream(ChangeFormatEnum.values()).filter(ChangeFormatEnum::getIsDefault)
                .collect(Collectors.toList())) {
            if (ArrayUtil.contains(value.getTypes(), o.getClass())) {
                return value.format.apply(o, field);
            }
        }
        return NULL;
    }


    /**
     * 类型格式化
     *
     * @param o 传入类型
     * @return 格式化后字符串
     */
    public String format(Object o, Field field) {
        if (ObjUtil.isEmpty(o) || StrUtil.isBlankOrUndefined(StrUtil.toString(o))) {
            return NULL;
        }
        return this.format.apply(o, field);
    }


}
